var Wami = window.Wami || {};

// A place to store non-anonymous callback functions.
Wami._callbacks = Wami._callbacks || {};

// This method ensures that a WAMI recorder is operational, and that
// the following API is available in the Wami namespace. All functions
// must be named (i.e. cannot be anonymous).
//
// Wami.startPlaying(url, startfn = null, finishedfn = null, failedfn = null);
// Wami.stopPlaying()
//
// Wami.startRecording(url, startfn = null, finishedfn = null, failedfn = null);
// Wami.stopRecording()
//
// Wami.getRecordingLevel() // Returns a number between 0 and 100
// Wami.getPlayingLevel() // Returns a number between 0 and 100
//
// Wami.hide()
// Wami.show()
//
// Manipulate the WAMI recorder's settings. Some settings will have
// to vary between Flash/Android/iPhone. In Flash, for instance,
// we need to check if the microphone permission has been granted.
// We might also set/return sample rate here, etc.
//
// Wami.getSettings();
// Wami.setSettings(options);
//
// Optional way to set up browser so that it's constantly listening
// This is to prepend audio in case the user starts talking before
// they click-to-talk.
//
// Wami.startListening()
// Wami.stopListening()
//
Wami.setup = function(id, callback) {
	if (Wami.startRecording) {
		// Wami's already defined
		callback();
		return;
	}

	function supportsTransparency() {
		// Detecting the OS is a big no-no in Javascript programming, but
		// I can't think of a better way to know if wmode is supported or
		// not... since NOT supporting it (like Flash on Ubuntu) is a bug.
		return (navigator.platform.indexOf("Linux") == -1);
	}

	// Embed the WAMI SWF and call the named callback function when loaded.
	function embedWamiSWF(id, initfn) {
		var flashVars = {
			visible : false,
			loadedCallback : initfn,
			localMode: true
		}

		var params = {
			allowScriptAccess : "always"
		}

		if (supportsTransparency()) {
			params.wmode = "transparent";
		}

		if (console) {
			flashVars.console = true;
		}

		var version = '10.0.0';
		document.getElementById(id).innerHTML = "WAMI requires Flash "
				+ version
				+ " or greater<br />https://get.adobe.com/flashplayer/";

		// This is the minimum size due to the microphone security panel
		swfobject.embedSWF("Wami.swf", id, 214, 137, version, null, flashVars,
				params);

		// Without this line, Firefox has a dotted outline of the flash
		swfobject.createCSS("#" + id, "outline:none");
	}

	// To check if the microphone settings were 'remembered', we
	// must actually embed an entirely new Wami client and check
	// whether its microphone is granted. If it is, it was remembered.
	function checkRemembered(finishedfn) {
		var id = "Wami-SWF" + Math.random();
		var div = document.createElement('div');
		div.style.top = '-999px';
		div.style.left = '-999px';
		div.setAttribute('id', id);
		var body = document.getElementsByTagName('body').item(0);
		body.appendChild(div);

		Wami._callbacks[id] = function() {
			var swf = document.getElementById(id);
			Wami._remembered = swf.getSettings().microphone.granted;
			var div = document.getElementById(id);
			swfobject.removeSWF(id);
			eval(finishedfn + "()");
		};
		
		embedWamiSWF(id, "Wami._callbacks['" + id + "']");
	}

	// Attach all the audio methods to the Wami namespace in the callback.
	function delegateWamiAPI() {
		var recorder = document.getElementById(id);

		function delegate(name) {
			Wami[name] = function() {
				return recorder[name].apply(recorder, arguments);
			}
		}

		delegate('startPlaying');
		delegate('stopPlaying');
		delegate('startRecording');
		delegate('stopRecording');
		delegate('startListening');
		delegate('stopListening');
		delegate('getRecordingLevel');
		delegate('getPlayingLevel');
		delegate('setSettings');
		delegate('getBase64AudioData');
		delegate('uploadAudio');

		// Append extra information about whether mic settings are sticky
		Wami.getSettings = function() {
			var settings = recorder.getSettings();
			settings.microphone.remembered = Wami._remembered;
			return settings;
		}

		Wami.showSecurity = function(panel, startfn, finishedfn, failfn) {
			Wami._callbacks['securitypanelclosed'] = function() {
				checkRemembered(finishedfn);
			}

			recorder.showSecurity(panel, startfn,
					"Wami._callbacks['securitypanelclosed']", failfn);
		}

		Wami.show = function() {
			if (!supportsTransparency()) {
				recorder.style.visibility = "visible";
			}
		}

		Wami.hide = function() {
			// Hiding flash in all the browsers is tricky. Please read:
			// https://code.google.com/p/wami-recorder/wiki/HidingFlash
			if (!supportsTransparency()) {
				recorder.style.visibility = "hidden";
			}
		}

		// If we already have permissions, they were previously 'remembered'
		Wami._remembered = recorder.getSettings().microphone.granted;

		callback();
	}

	//
	// These lines initialize the SWF you see for security settings...
	//
	Wami._callbacks['initswf'] = delegateWamiAPI;
	embedWamiSWF(id, "Wami._callbacks['initswf']");
}

/*
 * Base64 encode/decode from http://ostermiller.org/calc/encode.html
 * (code published under GPLv2 License)
 */
var END_OF_INPUT = -1;
var base64Chars = new Array(
		'A','B','C','D','E','F','G','H',
		'I','J','K','L','M','N','O','P',
		'Q','R','S','T','U','V','W','X',
		'Y','Z','a','b','c','d','e','f',
		'g','h','i','j','k','l','m','n',
		'o','p','q','r','s','t','u','v',
		'w','x','y','z','0','1','2','3',
		'4','5','6','7','8','9','+','/'
		);
var reverseBase64Chars = new Array();
for (var i=0; i < base64Chars.length; i++){
	reverseBase64Chars[base64Chars[i]] = i;
}
var base64Str;
var base64Count;
function setBase64Str(str){
	base64Str = str;
	base64Count = 0;
}
function readReverseBase64(){
	if (!base64Str) return END_OF_INPUT;
	while (true){
		if (base64Count >= base64Str.length) return END_OF_INPUT;
		var nextCharacter = base64Str.charAt(base64Count);
		base64Count++;
		if (reverseBase64Chars[nextCharacter]){
			return reverseBase64Chars[nextCharacter];
		}
		if (nextCharacter == 'A') return 0;
	}
	return END_OF_INPUT;
}
function ntos(n){
	n=n.toString(16);
	if (n.length == 1) n="0"+n;
	n="%"+n;
	return unescape(n);
}
function decodeBase64(str){
	setBase64Str(str);
	var result = "";
	var inBuffer = new Array(4);
	var done = false;
	while (!done && (inBuffer[0] = readReverseBase64()) != END_OF_INPUT
			&& (inBuffer[1] = readReverseBase64()) != END_OF_INPUT){
		inBuffer[2] = readReverseBase64();
		inBuffer[3] = readReverseBase64();
		result += ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
		if (inBuffer[2] != END_OF_INPUT){
			result += ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
			if (inBuffer[3] != END_OF_INPUT){
				result += ntos((((inBuffer[2] << 6) & 0xff) | inBuffer[3]));
			} else {
				done = true;
			}
		} else {
			done = true;
		}
	}
	return result;
}

Wami.uploadRecordedFile = function(url) {
	// get the binary audio file content
	var base64audioBytes = Wami.getBase64AudioData();
	var audioBytes = decodeBase64(base64audioBytes);

	var crlf = '\r\n';
	var body = '';
	var doubleDash = '--';
	var boundary = '12345678901234567890';

	var file = {
		name: "online-recording.wav",
		type: "audio/x-wav",
		size: audioBytes.length,
		recordedContent: audioBytes
	};

	var body = doubleDash + boundary + crlf +
		'Content-Disposition: form-data; name="file"; ' +
		'filename="' + unescape(encodeURIComponent(file.name)) + '"' + crlf +
		'Content-Type: ' + file.type + crlf + crlf +
		file.recordedContent + crlf +
		doubleDash + boundary + doubleDash + crlf;

	// copy binary content into a ByteArray structure, so that the browser doesn't mess up encoding
	var audioByteArray = new Uint8Array(body.length);

	for (var i=0; i< audioByteArray.length; i++) {
		audioByteArray[i] = body.charCodeAt(i);
	}

	// use an XMLHttpRequest to upload the file
	var xhr = new XMLHttpRequest();
	xhr.onreadystatechange = function() {
		console.log(xhr.readyState);
	};
	xhr.open('post', url, true);
	xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
	//xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
	/

	// setup AJAX event handlers
	xhr.onload = function (e) { console.log('Upload complete: ' + e); };
	xhr.onabort = function (e) { console.log('Upload aborted: ' + e); };
	xhr.onerror = function (e) { console.log('Error while uploading: '); console.log(e); };

	xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
	xhr.send(audioByteArray.buffer);
	console.log("XHR sent");

}

